package br.com.management.mentor.controller.auth;

import java.util.Date;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;

import org.hibernate.validator.constraints.NotEmpty;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.security.access.annotation.Secured;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated;

import br.com.management.mentor.model.entities.auth.User;
import br.com.management.mentor.model.repositories.PermissionsRepository;
import br.com.management.mentor.model.repositories.UsersRepository;

@Validated
@Component
public class UserController {

	@Autowired
	private AuthenticationManager am;

	@Autowired
	private ApplicationContext context;
	
	@Autowired
	private EntityManagerFactory emf;
	
	@Autowired
	private PermissionsRepository permissionsRepository;
	
	@Autowired
	private UsersRepository usersRepository;
	
	@Autowired
	private PasswordEncoder passwordEncoder;
	
	@Secured( { "ROLE_MANAGE_USERS" , "ROLE_ADMIN" } )
	public User create( User u ) {
		EntityManager em = emf.createEntityManager();
		
		Date currentDate = new Date();
		u.setEnabled( true );
		u.setCreationDate( currentDate );
		u.setUpdatedDate( currentDate );
		if( u.getPassword() != null ) u.setPassword( passwordEncoder.encode( u.getPassword() ) );
		
		u.getPermissions().add( permissionsRepository.getDefault() );
			
		try {
			em.getTransaction().begin();
			em.persist( u );
			em.getTransaction().commit();
			return u;
		} finally {
			if ( em != null ) em.close();
		}
	}

	@Secured( { "ROLE_MANAGE_USERS" , "ROLE_ADMIN" } )
	public User update( User u ) {
		EntityManager em = emf.createEntityManager();
		u.setUpdatedDate( new Date() );
		try {
			em.getTransaction().begin();
			em.merge( u );
			em.getTransaction().commit();
			return u;
		} finally {
			if ( em != null ) em.close();
		}
	}

	@Secured( { "ROLE_MANAGE_USERS" , "ROLE_ADMIN" } )
	public User delete( User u ) {
		EntityManager em = emf.createEntityManager();
		
		u = em.find( u.getClass() , u.getId() );
		
		u.setEnabled( false );
		u.setUpdatedDate( new Date() );
		
		try {
			em.getTransaction().begin();
			em.merge( u );
			em.getTransaction().commit();
			return u;
		} finally {
			if ( em != null ) em.close();
		}
	}

	@Secured( { "ROLE_MANAGE_USERS" , "ROLE_ADMIN" } )
	public List<User> find( String username , int firstResult, int maxResults ) {
		return usersRepository.getActivesByUsername( username , firstResult , maxResults );
	}

	@Secured( { "ROLE_USER" } )
	public User recoverPassword( String username ) {
		return null;
	}
	
	@Secured( { "ROLE_USER" } )
	public User changePassword( User u ) {
		return null;
	}
	
	@Secured( { "ROLE_USER" } )
	public void logout() {
		SecurityContextHolder.getContext().getAuthentication().setAuthenticated( false );
		SecurityContextHolder.getContext().setAuthentication( null );
		SecurityContextHolder.clearContext();
	}

	public User login( @NotEmpty String username , @NotEmpty String password ) {
		Authentication request = new UsernamePasswordAuthenticationToken( username , password );
		Authentication result = am.authenticate( request );
		SecurityContextHolder.getContext().setAuthentication( result );
		return (User) result.getPrincipal();
	}

}